/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ObjectHandler;

import Support.WriteString;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.nio.ByteBuffer;

/**
 *
 * @author Cong
 */
public class LanSupportMessage {

    /**
     * define message type
     */
    public static final String CloseConnection = "-1";
    public static final String CheckConnection = "0";
    public static final String ChatMessageType = "1";
    public static final String ServerToClientMessageType = "2";
    public static final String FileType = "3";
    public static final String ClientScreenshotType = "4";
    public static final String ViewScreenImage = "5";
    public static final String StartViewScreen = "6";
    public static final String StopViewScreen = "7";
    public static final String StartRemoteDesktop = "8";
    public static final String StopRemoteDesktop = "9";
    public static final String ViewRemoteDesktop = "10";
    public static final String LeftMouseClick = "11";
    public static final String WheelMouseClick = "14";
    public static final String RightMouseClick = "12";
    public static final String MouseRelease = "13";
    public static final String WheelMouseRelease = "15";
    public static final String RightMouseRelease = "16";
    public static final String MouseMoved = "17";
    public static final String keyPress = "18";
    public static final String keyRelease = "19";
    public static final String Shellcmd = "20";
    public static final String ShellMessage = "21";
    public static final String ClientRefuseShell = "22";
    public static final String ClientScreenSize = "23";
    public static final int BlockSize = 1024;
    /**
     *
     * default type CheckConnection
     */
    private String Type = CheckConnection;

    public void setType(String Type) {
        this.Type = Type;
    }

    public void setData(byte[] Data) {
        this.Data = Data;
    }
    /**
     *
     * byte[] byteData
     */
    private byte[] Data;

    public String getType() {
        return Type;
    }

    public byte[] getData() {
        return Data;
    }
    private Support.WriteString writer;
    private boolean debug = true;

    public LanSupportMessage(String type) {
        writer = new WriteString(debug);
        Type = type;
    }

    public LanSupportMessage() {
        writer = new WriteString(debug);
    }

    public byte[] GetBytes() {
        //data length + header
        int length = 0;
        if (Data != null) {
            length = Data.length;
        }
        byte[] message = new byte[length + 9];
        message[0] = new Byte(Type);
        byte[] lengthInBytes = _long2Bytes(length);
        System.arraycopy(lengthInBytes, 0, message, 1, 8);
        if (Data != null) {
            System.arraycopy(Data, 0, message, 9, Data.length);
        }
        return message;
    }

    public void Send(Socket sendSocket) {
        try {
            byte[] bs = GetBytes();
            BufferedOutputStream bos = new BufferedOutputStream(sendSocket.getOutputStream());
            bos.write(bs, 0, bs.length);
            bos.flush();
        } catch (IOException ex) {
        }
    }

    /**
     * 0 : no error -1 : the socket is closed or the socket is not connected
     *
     * @param listenSocket
     * @return int error
     */
    public int Receive(Socket listenSocket) {
        InputStream inputStream;
        byte[] lengInBytes = new byte[8];
        int pos = 0;
        try {
            inputStream = listenSocket.getInputStream();
            Type = String.valueOf(inputStream.read());
            inputStream.read(lengInBytes, 0, 8);
            int length = (int) _bytes2Long(lengInBytes);
            this.Data = new byte[length];

            while (length > pos) {
                int len;
                if (LanSupportMessage.BlockSize < length - pos) {
                    len = LanSupportMessage.BlockSize;
                } else {
                    len = length - pos;
                }
                pos += inputStream.read(Data, pos, len);
            }
        } catch (IOException ex) {
            return -1;
        }
        return 0;
    }

    public void _clearData() {
        Type = "0";
        this.Data = null;
    }

    private long _bytes2Long(byte[] bs) {
        long value = 0;
        for (int i = 0; i < bs.length; i++) {
            byte c = bs[i];
            value = (value << 8) + (c & 0xff);
        }
        return value;
    }

    private byte[] _long2Bytes(long l) {
        ByteBuffer byteBuffer = ByteBuffer.allocate(8);
        byteBuffer.putLong(l);
        byte[] byteResult = byteBuffer.array();
        return byteResult;
    }
}
